﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.Windows.Forms;
using System.Xml;
using SdmxMl.Manager;
using System.Security.Principal;

namespace SdmxMl.Panels
{
    /// <summary>
    /// Dialog for selecting artefacts and testing REST consultation service syntax
    /// </summary>
    public partial class DlgRestSyntaxWizard : Form
    {
        #region Internal Members

        public ArtefactComboSelector artefactsSelector;

        #endregion

        #region Constructor

        public DlgRestSyntaxWizard()
        {
            InitializeComponent();

            // Fill combo Artefact types
            artefactsSelector = new ArtefactComboSelector(comboBoxArtefactType, comboBoxAgency, comboBoxArtefactId, comboBoxVersion);
            artefactsSelector.RestSyntax = true;
            artefactsSelector.InitComboContent();

            // Default to first item in each combo
            comboBoxDetail.SelectedIndex = 0;
            comboBoxReferences.SelectedIndex = 0;

            // Default or retrieves REST service entry-point
            textBoxEntryPoint.Text = ArtefactTypeToRest.RestSdmxBase;
        }
        #endregion

        #region Events

        private void buttonSubmit_Click(object sender, EventArgs e)
        {
            try
            {
                textBoxSyntax.Text = ComposeRestSyntax();
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private string ComposeRestSyntax()
        {
            // Ensure service entry point is defined
            if (textBoxEntryPoint.Text.Trim() == string.Empty)
                throw new ApplicationException("Service entry point must be specified.");

            // Generate REST call
            artefactsSelector.GetSelections();

            // Text to type
            string arType = ArtefactTypeToRest.RestType(artefactsSelector.ArtefactType);

            string syntax = textBoxEntryPoint.Text + '/' +

               arType + '/' +
               artefactsSelector.CodedAgency + '/' +
               artefactsSelector.CodedArtefact + '/' +
               artefactsSelector.CodedVersion;
            if (comboBoxDetail.SelectedIndex >= 0 || comboBoxReferences.SelectedIndex > 0)
            {
                syntax += "?";
            }
            if (comboBoxDetail.SelectedIndex >= 0)
            {
                syntax += "detail=";
                syntax += GetSubject(comboBoxDetail.SelectedItem.ToString());
            }
            if (comboBoxDetail.SelectedIndex >= 0 && comboBoxReferences.SelectedIndex > 0)
            {
                syntax += "&";
            }
            if (comboBoxReferences.SelectedIndex > 0)
            {
                syntax += "references=";
                syntax += GetSubject(comboBoxReferences.SelectedItem.ToString());
            }

            return syntax;
        }

        private string GetSubject(string subjectAndComment)
        {
            string[] arr = subjectAndComment.Split('-');
            return arr[0].Trim();
        }
        

        private void buttonInvoke_Click(object sender, EventArgs e)
        {

            try
            {
                // Generates syntax first
                textBoxSyntax.Text = ComposeRestSyntax();
                textBoxSyntax.Refresh();

                string uriText = textBoxSyntax.Text.Trim();

                Uri uri = new Uri(uriText);
                WebClient webclient = new WebClient();
            //    webclient.UseDefaultCredentials = true;
                
                WindowsIdentity wi = System.Security.Principal.WindowsIdentity.GetCurrent();
                
               // ICredentials credentials = CredentialCache.DefaultCredentials;
               // NetworkCredential credential = credentials.GetCredential(uri, System.Net.IAuthenticationModule.AuthenticationType);
  //              webclient.Credentials = CredentialCache.DefaultNetworkCredentials;
  //              webclient.Credentials = new NetworkCredential(wi.Name, "Mlp'nko=");

                using (new SdmxMl.Helper.CWaitCursor())
                {
                    XmlDocument XDoc = new XmlDocument();
                    XDoc.Load(webclient.OpenRead(uri));
                    ReferenceManager.TreeMgr.LoadSdmxArtefact(null, true, XDoc);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to read from URI. Reasion is: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        #endregion
    }

    /// <summary>
    /// Convertor between artefact type and corresponding item in REST syntax
    /// </summary>
    public class ArtefactTypeToRest
    {
        // REST entries
        private const string TAG_REST_SDMX_POINT = "RestEntryPoint";
        private const string TAG_REST_EXPORT_POINT = "RestExportPoint";

        public static Dictionary<SdmxArtefactType, string> dicoRestType;

        /// <summary> Static C'tor </summary>
        static ArtefactTypeToRest()
        {
            dicoRestType = new Dictionary<SdmxArtefactType, string>();

            dicoRestType.Add(SdmxArtefactType.CodeLists, "codelist");
            dicoRestType.Add(SdmxArtefactType.CategorySchemes, "categoryscheme");
            dicoRestType.Add(SdmxArtefactType.Concepts, "conceptscheme");
            dicoRestType.Add(SdmxArtefactType.HierarchicalCodelists, "hierarchicalcodelist");
            dicoRestType.Add(SdmxArtefactType.OrganisationSchemes, "organisationscheme");
            dicoRestType.Add(SdmxArtefactType.Dataflows, "dataflow");
            dicoRestType.Add(SdmxArtefactType.Metadataflows, "metadataflow");
            dicoRestType.Add(SdmxArtefactType.ReportingTaxonomies, "reportingtaxonomy");
            dicoRestType.Add(SdmxArtefactType.Processes, "process");
            dicoRestType.Add(SdmxArtefactType.MetadataStructureDefinitions, "metadatastructure");
            dicoRestType.Add(SdmxArtefactType.KeyFamilies, "datastructure");
            dicoRestType.Add(SdmxArtefactType.MetadataSet, "metadataset");
            dicoRestType.Add(SdmxArtefactType.Categorisations, "categorisation");
            dicoRestType.Add(SdmxArtefactType.StructureSets, "structureset");

        }

        public static string RestType(SdmxArtefactType arType)
        {
            string restType = string.Empty;
            foreach (SdmxArtefactType atype in Enum.GetValues(typeof(SdmxArtefactType)))
            {
                if (atype == arType)
                {
                    if (ArtefactTypeToRest.dicoRestType.ContainsKey(atype))
                    {
                        restType = ArtefactTypeToRest.dicoRestType[atype];
                        break;
                    }
                    else
                        throw new ApplicationException("Unsupported type: " + atype.ToString());
                }
            }
            return restType;
        }

        public static string RestExportBase
        {
            get
            {
                string restBase = string.Empty;
                if (ConfigurationManager.AppSettings[TAG_REST_EXPORT_POINT] != null &&
                    ConfigurationManager.AppSettings[TAG_REST_EXPORT_POINT].ToString().Trim() != string.Empty)
                    restBase = ConfigurationManager.AppSettings[TAG_REST_EXPORT_POINT].ToString().Trim();
                return restBase;
            }
        }

        public static string RestSdmxBase
        {
            get
            {
                string restBase = string.Empty;
                if (ConfigurationManager.AppSettings[TAG_REST_SDMX_POINT] != null &&
                    ConfigurationManager.AppSettings[TAG_REST_SDMX_POINT].ToString().Trim() != string.Empty)
                    restBase = ConfigurationManager.AppSettings[TAG_REST_SDMX_POINT].ToString().Trim();
                return restBase;
            }
        }
    }
}
